package ucenter

import (
	"fmt"
	"github.com/jinzhu/gorm"
	"go_api/pkg/setting"
	"log"
	"time"
)

var udb *gorm.DB


func SetupUcMysql() {
	var err error
	udb, err = gorm.Open(setting.UCenterSetting.Type, fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=True&loc=Local",
		setting.UCenterSetting.User,
		setting.UCenterSetting.Password,
		setting.UCenterSetting.Host,
		setting.UCenterSetting.Name))

	if err != nil {
		log.Fatalf("ucmysql.Setup err: %v", err)
	}

	gorm.DefaultTableNameHandler = func(udb *gorm.DB, defaultTableName string) string {
		//标前缀 setting.DatabaseSetting.TablePrefix
		//return setting.UCenterSetting.TablePrefix + defaultTableName
		return  defaultTableName
	}

	//db.SingularTable(true)
	udb.Callback().Create().Replace("gorm:update_time_stamp",updateTimeStampForCreateCallback)
	udb.Callback().Update().Replace("gorm:update_time_stamp",updateTimeStampForUpdateCallback)
	udb.Callback().Delete().Replace("gorm:delete_time_stamp", deleteTimeStampForDeleteCallback)
	udb.DB().SetMaxIdleConns(10)
	udb.DB().SetMaxOpenConns(100)
}

func CloseDB() {
	defer udb.Close()
}
var nowFunc = func() time.Time{
	return time.Now()
}

// updateTimeStampForCreateCallback will set `CreatedOn`, `ModifiedOn` when creating
func updateTimeStampForCreateCallback(scope *gorm.Scope) {
	if !scope.HasError() {
		now := nowFunc()
		if createdAtField, ok := scope.FieldByName("CreatedAt"); ok {
			if createdAtField.IsBlank {
				createdAtField.Set(now)
			}
		}

		if updatedAtField, ok := scope.FieldByName("UpdatedAt"); ok {
			if updatedAtField.IsBlank {
				updatedAtField.Set(now)
			}
		}

		//if deletedAtField, ok := scope.FieldByName("DeletedAt"); ok {
		//	if deletedAtField.IsBlank {
		//		deletedAtField.Set(nil)
		//	}
		//}
	}
}

// updateTimeStampForUpdateCallback will set `ModifiedOn` when updating
func updateTimeStampForUpdateCallback(scope *gorm.Scope) {
	if _, ok := scope.Get("gorm:update_at"); !ok {
		now := nowFunc()
		scope.SetColumn("UpdatedAt", now)
	}
}

func deleteTimeStampForDeleteCallback(scope *gorm.Scope) {
	if !scope.HasError() {
		var extraOption string
		str, ok := scope.Get("gorm:delete_option")
		if ok {
			extraOption = fmt.Sprint(str)
		}
		deletedAtField, hasDeletedAtField := scope.FieldByName("DeletedAt")
		if !scope.Search.Unscoped && hasDeletedAtField {
			scope.Raw(fmt.Sprintf(
				"UPDATE %v SET %v=%v%v%v",
				scope.QuotedTableName(),
				scope.Quote(deletedAtField.DBName),
				scope.AddToVars(time.Now().Unix()),
				addExtraSpaceIfExist(scope.CombinedConditionSql()),
				addExtraSpaceIfExist(extraOption),
			)).Exec()
		} else {
			scope.Raw(fmt.Sprintf(
				"DELETE FROM %v%v%v",
				scope.QuotedTableName(),
				addExtraSpaceIfExist(scope.CombinedConditionSql()),
				addExtraSpaceIfExist(extraOption),
			)).Exec()
		}
	}
}

func addExtraSpaceIfExist(str string) string {
	if str != "" {
		return " " + str
	}
	return ""
}